package com.zjhcsoft.auth.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zjhcsoft.auth.common.enums.PasswordType;
import com.zjhcsoft.auth.common.enums.StatusCode;
import com.zjhcsoft.auth.common.enums.UserCredentialType;
import com.zjhcsoft.auth.common.utils.RandomUtils;
import com.zjhcsoft.auth.common.vo.Result;
import com.zjhcsoft.auth.entity.Account;
import com.zjhcsoft.auth.entity.AppResource;
import com.zjhcsoft.auth.entity.Password;
import com.zjhcsoft.auth.entity.User;
import com.zjhcsoft.auth.entity.UserCredential;
import com.zjhcsoft.auth.entity.UserDevice;
import com.zjhcsoft.auth.entity.web.RegisterAcct;
import com.zjhcsoft.auth.entity.web.RegisterRequest;
import com.zjhcsoft.auth.service.AccountService;
import com.zjhcsoft.auth.service.AppResourceService;
import com.zjhcsoft.auth.service.PasswordService;
import com.zjhcsoft.auth.service.RegisterService;
import com.zjhcsoft.auth.service.SmsService;
import com.zjhcsoft.auth.service.UserCredentialService;
import com.zjhcsoft.auth.service.UserDeviceService;
import com.zjhcsoft.auth.service.UserService;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @Author: wzya
 * @Date: 2021/3/23
 */
@Service
public class RegisterServiceImpl implements RegisterService {
    @Autowired
    SmsService smsService;
    @Autowired
    UserCredentialService credentialService;
    @Autowired
    UserService userService;
    @Autowired
    UserDeviceService deviceService;
    @Autowired
    AppResourceService appService;
    @Autowired
    AccountService accountService;
    @Autowired
    PasswordService passwordService;

    @Override
    @Transactional
    public Result register(RegisterRequest request) {
        System.out.println("");
        //获取业务系统信息
        List<String> channelCodes = request.getChannelArray()
                .stream()
                .map(channel -> channel.getChannelCode()).collect(Collectors.toList());
        List<AppResource> apps = appService.getAppResourceByChannelCodesAndCorporationCode(channelCodes,request.getCorporationCode());
        List<Long> appIds = apps.stream().map(details->details.getId()).collect(Collectors.toList());

        /*-----------凭证校验---------------*/
        Map<Boolean,List<Result>> credentialsMap = request.getRegisterAcctArray().stream().map(registerAcct -> {
            if(!credentialsRepeatValidate(registerAcct.getAcctNo(), registerAcct.getAcctType(), appIds)){
                return Result.error(registerAcct.getAcctNo()+" has been registered.");
            }else {
                return Result.ok(registerAcct);
            }
        }).collect(Collectors.groupingBy(Result::isSuccess));

        if(credentialsMap.containsKey(false)){
            return Result.error(JSON.toJSONString(credentialsMap.get(false)));
        }

        /*-----------密码校验---------start----------*/
        //校验短信验证码
        if (StringUtils.isNotEmpty(request.getSmsVrfcCd())) {
            String mobile = request.getRegisterAcctArray().stream().filter(registerAcct ->
                registerAcct.getAcctType().contains(UserCredentialType.MOBILE.getCode())).findFirst().get().getAcctNo();
            if(!smsService.smsMsgValidate(mobile,request.getSmsVrfcCd())){
                return Result.error("sms verification code error.");
            }
        }

        //password验证码
        String lastPassword = null;
        if ( null != request.getPassword()) {
            // TODO..密码安全检验
           if(passwordService.passwordComplexityValidate(request.getPassword())) {
               // TODO..密码转化
               lastPassword = request.getPassword();
           }else {
               return Result.error("the password does not meet the security policy.");
           }

        }else {
            return Result.error("password is null.");
        }
        /*-----------密码校验---------end----------*/

        /*
        CREDENTIALS
        * 认证阶段通过，进入注册信息录入流程
        */
        //新建用户
        User user = JSON.parseObject(JSON.toJSONString(request),User.class);
        user.setCreatedTime(new Date());
        user.setUpdatedTime(new Date());
        userService.save(user);

        //保存账号信息
        List<Account> accounts = apps.stream().map(app -> new Account(){
            {
                setAppId(app.getId());
                setTodayErrorTimes("0");
                setContinuousErrorTimes("0");
                setClientStatus("0");
                setSysUserId(user.getId());
            }}).collect(Collectors.toList());
        accountService.saveBatch(accounts);
        //保存凭证 ...Todo
        List<UserCredential> credentials = credentialsMap.get(true).stream().map(result -> {
            RegisterAcct registerAcct = (RegisterAcct)result.getData();
            return accounts.stream().map(account -> new UserCredential(){
                {
                    setCredential(registerAcct.getAcctNo());setCredentialType(registerAcct.getAcctType());setCredentialStatus(StatusCode.ON.getCode());setAccountId(account.getId());}}).collect(Collectors.toList());
         }).flatMap(list->list.stream()).collect(Collectors.toList());
        credentialService.saveBatch(credentials);

        //保存密码
        String finalLastPassword = lastPassword;
        List<Password> passwordList = accounts.stream().map(account -> new Password(){{setCheckType(PasswordType.STATIC.getCode());setAccountId(account.getId());setPasswordStatus(StatusCode.ON.getCode());setPassward(finalLastPassword);}}).collect(Collectors.toList());
        passwordService.saveBatch(passwordList);

        //注册设备绑定
        if(!request.getSeId().isEmpty()){
            List<UserDevice> devices = accounts.stream().map(account -> new UserDevice(){{setSeId(request.getSeId());setAccountId(account.getId());}}).collect(Collectors.toList());
            deviceService.saveBatch(devices);
        }
        //保存操作记录 TODO..
        JSONObject object = new JSONObject();
        object.put("userId",user.getId());
        return Result.ok(object);
    }

    /*
     * 凭证重复查询
     */
    public Boolean credentialsRepeatValidate(String credential, String credentialType,List<Long> appIds){
        LambdaQueryWrapper<UserCredential> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserCredential::getCredentialType, credentialType).eq(UserCredential::getCredential, credential);
        List<UserCredential> credentials = credentialService.list(wrapper);
        if(null!=credentials && credentials.size()>0){
            List<Long> registeredAppIds = accountService
                    .listByIds(
                            credentials.stream().map(userCredential->userCredential.getAccountId()).collect(Collectors.toList())
                    ).stream().map(account -> account.getAppId()).collect(Collectors.toList());
            if(!Collections.disjoint(registeredAppIds,appIds)){
                return false;
            }
        }
        return true;
    }


    /*
    * 临时构建凭证账号信息
    * */
//    private void temStoreCredentials(String credential,String credentialType,String secondType,List<AppResource> apps,List<UserCredential> credentials){
//        apps.stream().forEach(details -> credentials.add(new UserCredential(){
//        {
//            setCredential(credential);
//            setCredentialType(credentialType);
//            if(details.getDefaultCredentialType().contains(credentialType)){
//                setCredentialStatus(0);
//            }else {
//                setCredentialStatus(1);
//            }
//        }
//        }));
//    }

    /*凭证校验*/
//    public  Result credentialsValidate(String credential,String credentialType,List<AppResource> apps){
//        Boolean credentialsValidateFlag = false; //凭证校验状态，至少有一个可用凭证
//
//        /*手机号校验*/
//        if (UserCredentialType.MOBILE.equals(credentialType)) {
//            if(MyUtils.MobileValidate(credential)){
//                if(!credentialsRepeatValidate(credential,"3",null,appIds)){
//                    return Result.error("mobile phone number has been registered.");
//                }
//            }else {
//                return Result.error("mobile phone number error.");
//            }
//            temStoreCredentials(request.getMobile(),"3",null,apps,credentials);
//            credentialsValidateFlag = true;
//
//        }
//        /*客户号校验*/
//        if (null != request.getClientNo()) {
//            if(!credentialsRepeatValidate(request.getClientNo(),"1",null,appIds)){
//                return Result.error("client_no has been registered.");
//            }
//            temStoreCredentials(request.getClientNo(),"1",null,apps,credentials);
//            credentialsValidateFlag = true;
//        }
//
//        /*证件号校验*/
//        if (null != request.getGlobalId() && null != request.getGlobalType()) {
//            if(!credentialsRepeatValidate(request.getGlobalId(),"2","1",appIds)){
//                return Result.error("global_id has been registered.");
//            }
//            temStoreCredentials(request.getGlobalId(),"1","1",apps,credentials);
//            credentialsValidateFlag = true;
//        }
//
//        /*别名校验*/
//        if (null != request.getNickName()) {
//            if(!credentialsRepeatValidate(request.getNickName(),"4",null,appIds)){
//                return Result.error("nickName has been registered.");
//            }
//            temStoreCredentials(request.getNickName(),"4",null,apps,credentials);
//            credentialsValidateFlag = true;
//        }
//        /*最后检验凭证可用性*/
//        if(!credentialsValidateFlag){
//            return Result.error("No credential information available.");
//        }else {
//            return Result.ok();
//        }
//    }



}
